package pl.com.ozzy.ozsign.ui;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Comparator;

import pl.com.ozzy.ozsign.lang.IUIListCallback;
import pl.com.ozzy.ozsign.lang.NamedSignature;
import pl.com.ozzy.ozsign.lang.SignaturesLoadTask;
import pl.com.ozzy.ozsign.tools.AppConfigManager;
import pl.com.ozzy.ozsign.tools.PreferencesWrapper;
import pl.com.ozzy.ozsign.tools.SignService;
import android.app.ListActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * This view is visible after application start. It contains main menu.
 */
public class MainUI extends ListActivity implements IUIListCallback {

	private final static String THIS_FILE = "MainUI";
	private SignatureListAdapter mAdapter;
	private TextView tvEmpty;
	private SignaturesLoadTask mTask;
	private final Comparator<NamedSignature> mSorter = new Comparator<NamedSignature>() {
		public int compare(NamedSignature firstSign, NamedSignature secondSign) {
			return firstSign.getName().compareTo(secondSign.getName());
		}
	};

	private static final int MENU_ID_RENAME = 1;
	private static final int MENU_ID_REMOVE = 2;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		mAdapter = new SignatureListAdapter(this);
		setListAdapter(mAdapter);

		tvEmpty = (TextView) findViewById(android.R.id.empty);
		loadSignatures();

		registerForContextMenu(getListView());

		PreferencesWrapper prefs = new PreferencesWrapper(this);

		/*
		 * If this is first application run or user want to reset all
		 * application settings run configuration welcome screen containing
		 * wizard.
		 */
		if (prefs.getBooleanValue(AppConfigManager.RESET_SETTINGS)) {
			prepareDirs();
			Intent wizardIntent = new Intent(this, WelcomeScreenUI.class);
			startActivityForResult(wizardIntent, 0);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.mi_close: {
			finish();
			break;
		}
		case R.id.mi_add_gesture: {
			Intent mIntent = new Intent(this, DrawPanelUI.class);
			startActivityForResult(mIntent, 0);
			break;
		}
		case R.id.mi_options: {
			/*
			 * Show options panel
			 */
			Intent mIntent = new Intent(this, OptionsUI.class);
			startActivityForResult(mIntent, 0);
			break;
		}
		}
		return super.onOptionsItemSelected(item);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onActivityResult(int, int,
	 * android.content.Intent)
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		Log.d("", "ACTIVITY RESULT : " + resultCode);
		switch (resultCode) {
		case AppConfigManager.STATUS_OPTIONS_CLOSED: {
			PreferencesWrapper prefs = new PreferencesWrapper(this);
			Intent mIntent = new Intent(this, SignService.class);
			if (prefs.getBooleanValue(AppConfigManager.USE_MEDIA_SCANNER)) {
				mIntent = new Intent(this, SignService.class);
				startService(mIntent);
			} else {
				stopService(mIntent);
			}
			break;
		}
		case AppConfigManager.STATUS_GESTURE_ADDED: {
			/*
			 * Reload signatures list
			 */
			loadSignatures();
			break;
		}
		case AppConfigManager.STATUS_OPTIONS_CANCELED: {
			Intent wizardIntent = new Intent(this, WelcomeScreenUI.class);
			startActivityForResult(wizardIntent, 0);
			break;
		}
		}

	}

	private void loadSignatures() {
		if (mTask != null
				&& mTask.getStatus() != SignaturesLoadTask.Status.FINISHED) {
			mTask.cancel(true);
		}
		mTask = (SignaturesLoadTask) new SignaturesLoadTask(this, mAdapter,
				this).execute();
	}

	@Override
	public void executeOnPost() {
		tvEmpty.setVisibility(View.VISIBLE);
		tvEmpty.setText(getString(R.string.msg_error_signatures_loading,
				AppConfigManager.mStoreFile.getAbsolutePath()));
	}

	@Override
	public void executeOnEmpty() {
		tvEmpty.setText(R.string.msg_signatures_empty);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenu.ContextMenuInfo menuInfo) {

		super.onCreateContextMenu(menu, v, menuInfo);

		AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
		menu.setHeaderTitle(((TextView) info.targetView).getText());

		menu.add(0, MENU_ID_RENAME, 0, "Podpisz");
		menu.add(0, MENU_ID_REMOVE, 0, "Sprawdź podpis");
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		final AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item
				.getMenuInfo();
		final NamedSignature signature = (NamedSignature) menuInfo.targetView
				.getTag();

		switch (item.getItemId()) {
		case MENU_ID_RENAME:
			setDefaultSignature(signature);
			return true;
		case MENU_ID_REMOVE:
			deleteSignature(signature);
			return true;
		}

		return super.onContextItemSelected(item);
	}

	private void prepareDirs() {
		File mFile = new File(AppConfigManager.mKeyStorePath);
		if (!mFile.exists()) {
			boolean state = mFile.mkdirs();
			if (!state) {
				Log.d(THIS_FILE, "Problem creating directories");
			}
		}
	}

	private void deleteSignature(NamedSignature signature) {
		AppConfigManager.gStore.removeGesture(signature.getName(),
				signature.getGesture());
		AppConfigManager.gStore.save();

		final SignatureListAdapter adapter = mAdapter;
		adapter.setNotifyOnChange(false);
		adapter.remove(signature);
		adapter.sort(mSorter);
		if (mAdapter.getCount() == 0) {
			tvEmpty.setText(R.string.msg_signatures_empty);
		}
		adapter.notifyDataSetChanged();

		Toast.makeText(this, R.string.msg_delete_success, Toast.LENGTH_SHORT)
				.show();
	}

	private void setDefaultSignature(NamedSignature signature) {
		Resources resources = getResources();
		int mPathColor = resources.getColor(R.color.gesture_color);
		int mThumbnailInset = (int) resources
				.getDimension(R.dimen.gesture_thumbnail_inset);
		int mThumbnailSize = (int) resources
				.getDimension(R.dimen.gesture_thumbnail_size);
		PreferencesWrapper prefs = new PreferencesWrapper(this);
		Bitmap mBitmap = signature.getGesture().toBitmap(mThumbnailSize,
				mThumbnailSize, mThumbnailInset, mPathColor);

		/*
		 * Get Bitmap object as byte array
		 */
		ByteArrayOutputStream mBos = new ByteArrayOutputStream();
		mBitmap.compress(CompressFormat.PNG, 0, mBos);
		byte[] digestBuf = mBos.toByteArray();

		/*
		 * Create MD5 hash
		 */
		MessageDigest mDigest;
		try {
			mDigest = MessageDigest.getInstance("MD5");
			mDigest.update(digestBuf);
			digestBuf = mDigest.digest(digestBuf);
			StringBuffer hexString = new StringBuffer();

			/*
			 * Rewrite hash to hex string
			 */
			for (int i = 0; i < digestBuf.length; i++) {
				hexString.append(Integer.toHexString(0xFF & digestBuf[i]));
			}
			String mName = new String(hexString);

			prefs.setStringValue(AppConfigManager.DEFAULT_SIGNATURE, mName);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}
}